package belf.migrate.engine.job.structure.helper;

import belf.migrate.api.exception.CatalogException;
import belf.migrate.api.exception.TableNotExistException;
import belf.migrate.api.model.QualifiersModel;
import belf.migrate.api.table.schema.AbstractSinkCatalog;
import belf.migrate.api.table.schema.CatalogTable;
import belf.migrate.api.table.schema.TablePath;
import belf.migrate.api.taskconf.JobContext;
import belf.migrate.api.type.DbObjectType;
import belf.migrate.api.type.LogLevelType;
import belf.migrate.api.util.PostLog;
import belf.migrate.engine.job.JobResult;
import belf.migrate.api.job.Job;
import belf.migrate.engine.job.JobResultItem;
import belf.migrate.api.taskconf.Task;
import belf.migrate.api.util.ExceptionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.util.*;

import static belf.migrate.api.job.JobCode.*;

/**
 * 删除目标表的工具
 */
@Slf4j
public class DropTableTool extends TableTool {
    private AbstractSinkCatalog catalog;

    private List<String> remainTables;

    private Map<String, CatalogTable> catalogTableMap = new HashMap<>();

    public DropTableTool(JobContext jobContext, Job job) {
        super(jobContext, job);
        this.catalog = jobContext.getSinkCatalog();

        // 若限定了要处理的表名称
        remainTables = job.getMissions();
        if (remainTables == null || remainTables.isEmpty()) {
            remainTables = new ArrayList<>();
            jobContext.getSinktableMap().values().forEach(catalogTable -> {
                remainTables.add(catalogTable.getTableId().getTableName());
            });
        }

        jobContext.getSinktableMap().values().forEach(catalogTable -> {
            catalogTableMap.put(catalogTable.getTableId().getTableName(), catalogTable);
        });

    }

    /**
     * 尝试删除所有的依赖的表
     */
    public JobResult run() {
        PostLog.sendLogModel(
                job.getJobId(),
                job.getTask().getTaskType().getName(),
                "删除表开始！",
                LogLevelType.INFO.getType(),
                EXECUTING,
                jobContext.getProgress());
        JobResult jobResult = new JobResult(SUCCESS, "删除选中的表成功");

        String databaseName = jobContext.getTaskConf().getSinkConf().getDatabaseName();
        String schemaName = jobContext.getTaskConf().getSinkConf().getSchemaName();

        QualifiersModel qualifiersModel = getSinkQualifiersModel();



        Iterator<String> it = remainTables.iterator();
        while (it.hasNext()) {
            String startTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS");
            String tableName = it.next();
            TablePath sinkPath = TablePath.of(databaseName, schemaName, tableName, qualifiersModel);

            try {
                jobContext.addProgress(DbObjectType.TABLE.getTypeName(), remainTables.size());
                catalog.dropTable(catalogTableMap.get(tableName).getTablePath(), true);
                log.info("Drop Table {} Successfully.", tableName);
                JobResultItem jobResultItem = new JobResultItem(tableName,
                        sinkPath.getCaseTableName(),
                        SUCCESS,
                        "删除表" + tableName + "成功");
                jobResultItem.setSinkDdl(catalog.getDropTableSql(sinkPath));
                jobResultItem.setStartTime(startTime);
                jobResultItem.setEndTime(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
                jobResultItem.setType(DbObjectType.SEQUENCE.getTypeName());
                jobResult.addItem(jobResultItem);

                PostLog.sendLogModel(
                        job.getJobId(),
                        job.getTask().getTaskType().getName(),
                        "删除表" + tableName + "成功",
                        LogLevelType.INFO.getType(),
                        EXECUTING,
                        jobContext.getProgress());

            } catch (TableNotExistException | CatalogException e) {
                e.printStackTrace();
                String endTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS");
                JobResultItem jobResultItem = new JobResultItem(tableName,
                        sinkPath.getCaseTableName(),
                        DROP_TABLE_ERROR,
                        "删除表" + tableName + "失败",
                        ExceptionUtils.toString(e),
                        DbObjectType.TABLE.getTypeName(),
                        startTime,
                        endTime,
                        null,
                        catalog.getDropTableSql(sinkPath));

                PostLog.sendLogModel(
                        job.getJobId(),
                        job.getTask().getTaskType().getName(),
                        "删除表" + tableName + "失败",
                        LogLevelType.ERROR.getType(),
                        EXECUTING,
                        jobContext.getProgress());

                jobResultItem.setStartTime(startTime);
                jobResultItem.setEndTime(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
                jobResultItem.setType(DbObjectType.SEQUENCE.getTypeName());

                jobResult.addItem(jobResultItem);
                if (jobResultItem.getCode() != SUCCESS
                        && job.getTask().getTaskPolicy() == Task.TaskPolicy.ERROR_STOP) {
                    break;  //删除表遇到错误即返回
                }
            }
        }
        if (jobResult.getFailtures() > 0) {
            jobResult.setCode(DROP_TABLE_ERROR);
            jobResult.setMessage("删除选中的表失败");
            log.error("Drop Some Tables Of {} Failed.", jobContext.getValidSinkDatabase());
        } else {
            log.info("Drop All Tables Of {} Successfully.", jobContext.getValidSinkDatabase());
        }
        PostLog.sendLogModel(
                job.getJobId(),
                job.getTask().getTaskType().getName(),
                "删除表结束！",
                LogLevelType.INFO.getType(),
                EXECUTING,
                jobContext.getProgress());
        return jobResult;
    }

}
